/*
 *   AS IS License
 * ==Naive Coders==
 */
package org.naive.data;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;

/**
 *
 * @author gbu.000
 */
public class Tree extends LinkedList<Tree> {

    private final NodeType type;
    private final Map<TreeAnnotation<Object>, Object> annotations = new HashMap<>();

    public Tree(NodeType type) {
        this.type = type;
    }

    public NodeType getType() {
        return type;
    }

    public <T> T getAnnotation(TreeAnnotation<T> a) {
        return (T) annotations.get(a);
    }

    public <T> void putAnnotation(TreeAnnotation<T> a, T value) {
        annotations.put(((TreeAnnotation<Object>)a), value);
    }

    public Tree copy() {
        Tree cm = new Tree(type);
        for (TreeAnnotation<Object> a : annotations.keySet()) {
            cm.putAnnotation(a, getAnnotation(a));
        }
        for (Tree cmc : this) {
            cm.add(cmc.copy());
        }
        return cm;
    }
    
    public int calcSize() {
        int i = 1;
        for(Tree t: this) {
            i += t.calcSize();
        }
        return i;
    }
    
    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        append(sb, "", this);
        return sb.toString();
    }

    protected void append(StringBuilder sb, String prefix, Tree t) {
        sb.append("\n");
        sb.append(prefix);
        sb.append(type);
        if(!annotations.isEmpty()) {
            sb.append("*");
        }
        for (Tree tt : t) {
            tt.append(sb, prefix + ": ", tt);
        }
    }
}
